#include <stdlib.h>
#include <string.h>
#include "hmac_md5.h"
#include "md5.h"

#define IPAD 0x36
#define OPAD 0x5c
#define MAX(x,y) ((x)>(y)?(x):(y))

void hmac_md5_init() {
    md5_init();
}

void hmac_md5(uint8_t *hmac, const uint8_t *message, uint64_t message_bytes, const uint8_t *key, uint64_t key_bytes) {
    if (key_bytes > BLOCK_BYTES) {
        memset(hmac, 0, 16);
        return;
    }
    uint8_t *tem = (uint8_t*)malloc(BLOCK_BYTES + MAX(message_bytes, 16));
    memcpy(tem, key, key_bytes);
    memset(tem + key_bytes, 0, BLOCK_BYTES - key_bytes);
    for (size_t i = 0; i < BLOCK_BYTES; ++i) {
        tem[i] ^= IPAD;
    }
    memcpy(tem + BLOCK_BYTES, message, message_bytes);
    md5(tem + BLOCK_BYTES, tem, BLOCK_BYTES + message_bytes);

    memcpy(tem, key, key_bytes);
    memset(tem + key_bytes, 0, BLOCK_BYTES - key_bytes);
    for (size_t i = 0; i < BLOCK_BYTES; ++i) {
        tem[i] ^= OPAD;
    }
    md5(hmac, tem, BLOCK_BYTES + 16);

    free(tem);
}
